from persistent import Persistent

from zope.component import adapts, getUtility
from zope.interface import implements, alsoProvides
from zope.app.intid.interfaces import IIntIdsQuery

from plone.app.multilingual.interfaces import *

from z3c.relationfield.interfaces import IHasRelations
from zope.app.intid.interfaces import IIntIds
from z3c.relationfield import RelationValue
from zc.relation.interfaces import ICatalog

from Products.CMFCore.utils import getToolByName

from zope.app.container.interfaces import IObjectAddedEvent 
from zope.event import notify
from zope.app.container.contained import Contained
from zope.component.exceptions import ComponentLookupError

from persistent.mapping import PersistentMapping

from zope.event import notify
from zope.lifecycleevent import ObjectModifiedEvent


class RelationTranslation(Persistent):
    implements(IRelationTranslation, IHasRelations)
    
    def __init__(self, destination, translationgroup, origin=None):
        intids = getUtility(IIntIds)
        destination_id = intids.getId(destination)
        self.rel = RelationValue(destination_id)
        self.origin = origin
        self.translationgroup = translationgroup

class TranslationGroup(Persistent, Contained ):
    ''' Translation group is the canonical object of the translation '''
    implements(ITranslationGroup)
    
    @property
    def uid(self):
        intids = getUtility(IIntIdsQuery)
        return intids.getId(self)

    authoritative = None
    # Dictionary about the language object relations
    languages = {}
    # Lang independent information of the object
    lang_independent = {}

    def addTranslation(self, language, context=None, origin=None, translatedObject=None, **kwargs):
        # Decide which is the translated object
        if context and not(translatedObject):
            destination = ITranslate(context).translate(language)
        elif translatedObject:
            destination = translatedObject
        else:
            raise KeyError, 'We can not define the destination object on translation'
            
        # Add to the translation dictionary
        self.languages[language] = RelationTranslation(destination, self, origin)
        notify(ObjectModifiedEvent(self))
        return destination
        
    def hasTranslation(self, language):
        return self.languages.has_key(language)
        
        
    def setAuthoritative(self, language):
        self.authoritative = language

    def removeTranslation(self, language):
        del(self.languages[language])
        pass

    def getTranslations(self):
        # TODO a list of translated objects
        return self.languages

    def getTranslation(self, language='language'):
        if self.languages.has_key(language):
            traduccions = self.languages[language].rel.to_object
        else:
            return None

    def getTranslationLanguages(self):
        return self.languages.keys()


    

class TranslationGroupAdapter(object):
    '''This adapter adapts an object to its translation group 
    '''
    implements(ITranslationGroupLookup)
    adapts(ITranslatable)

    _translation_group = None

    def __init__(self, context):
        transutility = getUtility(ITranslationUtility,name=u'TranslationUtility')
        ptool = getToolByName(context, "portal_properties").multilingual_properties
        types = ptool.supported_types
        # See if it's on supported types
        if context.portal_type in types:
            catalog = getUtility(ICatalog)
            intids = getUtility(IIntIds)
            sources = sorted(catalog.findRelations({'to_id': intids.getId(context), 'from_interfaces_flattened': IRelationTranslation}))
            if not sources:
                # In case there is no translation group of this element
                self._translation_group = transutility.addTranslationGroup(language=context.Language(), object=context)
            elif sources:
                self._translation_group = sources[0].from_object.translationgroup
        else:
            raise NotTranslatable, 'Not type supported to translate'

    def __str__(self):
        translations = self.getTranslations()
        result = ""
        for translation in translations:
            result += translation.getId()+"\n"
        return result

    def getTranslationGroup(self):
        return self._translation_group

    # Wrapper of translation group methods

    def addTranslation(self, language, context):
        plang = getToolByName(context, 'portal_languages')
        if language in plang.supported_langs:
            destination = self._translation_group.addTranslation(language,origin=context.language, context=context)
        return destination
            
    def hasTranslation(self, language):
        self._translation_group.hasTranslation(language)
        
    def removeTranslation(self, language):
        self._translation_group.removeTranslation(language)

    def getTranslations(self):
        return self._translation_group.getTranslations()

    def getTranslation(self,language='language'):
        return self._translation_group.getTranslation(language)

    def getTranslationLanguages(self):
        return self._translation_group.getTranslationLanguages()
        
    def getTranslationChain(self):
        """ it should return the translation chain"""



